package luadb

import (
	"database/sql"
	"encoding/json"
	"errors"
	"io/ioutil"
	"time"

	"gitee.com/haodreams/godriver/opdb/opsql"
	"gitee.com/haodreams/godriver/sqlite3"
	"gitee.com/haodreams/golib/logs"
	"gorm.io/driver/clickhouse"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
)

const luaRowsTypeName = "rows"

// const luaSessionTypeName = "session"
// const luaTxTypeName = "transaction"
var boss *Boss = new(Boss)

//database 。
type database struct {
	Name   string `json:"name"`
	Driver string `json:"driver"`
	Source string `json:"source"`
}

func init() {
	boss.init()
}

//LoadDefaultDBs 加载默认的DB
func LoadDefaultDBs(dbPaths ...string) {
	boss.LoadDefaultDBs(dbPaths...)
}

//Boss 管理服务
type Boss struct {
	//task *cron.Cron
	dbs map[string]*gorm.DB
}

func (m *Boss) init() {
	m.dbs = map[string]*gorm.DB{}

	// InitSyncLua("lua/", cb)
	// InitAsynLua("lua/", cb)
}

//LoadDefaultDBs 加载默认的DB
func (m *Boss) LoadDefaultDBs(dbPaths ...string) {
	dbPath := "db.json"
	if len(dbPaths) > 0 && dbPaths[0] != "" {
		dbPath = dbPaths[0]
	}
	data, err := ioutil.ReadFile(dbPath)
	if err != nil {
		logs.Error(err.Error())
	}
	var dbs []*database
	err = json.Unmarshal(data, &dbs)
	if err != nil {
		logs.Error(err.Error())
	}
	for _, d := range dbs {
		if d.Driver == "" {
			continue
		}
		if d.Source == "" {
			continue
		}

		var db *gorm.DB
		switch d.Driver {
		case "sqlite3":
			db, err = gorm.Open(sqlite3.Open(d.Source), &gorm.Config{
				NamingStrategy: schema.NamingStrategy{
					SingularTable: true,
				},
			})
		case "mysql":
			db, err = gorm.Open(mysql.Open(d.Source), &gorm.Config{
				NamingStrategy: schema.NamingStrategy{
					SingularTable: true,
				},
			})
		case "clickhouse":
			db, err = gorm.Open(clickhouse.Open(d.Source), &gorm.Config{
				NamingStrategy: schema.NamingStrategy{
					SingularTable: true,
				},
			})
		case "opsql":
			db, err = gorm.Open(opsql.Open(d.Source), &gorm.Config{
				NamingStrategy: schema.NamingStrategy{
					SingularTable: true,
				},
			})
		default:
			logs.Error("不支持的驱动", d.Driver)
			continue
		}
		if err != nil {
			logs.Error(err)
			continue
		}
		gdb, err := db.DB()
		if err != nil {
			logs.Error("db 错误", d.Driver)
			continue
		}
		gdb.SetConnMaxLifetime(time.Second * 1800)
		m.dbs[d.Name] = db
	}
}

//GetDB 获取数据库引擎
func GetDB(name string) (engine *gorm.DB) {
	engine = boss.dbs[name]
	return
}

//AddDB 添加一个db驱动
func AddDB(name string, engine *gorm.DB) {
	boss.dbs[name] = engine
}

//Exec 执行SQL语句
func (m *Boss) Exec(d string, sql string) (int64, error) {
	if db, ok := m.dbs[d]; ok {
		newdb := db.Exec(sql)
		err := newdb.Error
		count := db.RowsAffected
		return count, err
	}
	return 0, errors.New("没有找到数据库")
}

//Query 查询
func (m *Boss) Query(d string, sql string) (*sql.Rows, error) {
	if db, ok := m.dbs[d]; ok {
		return db.Raw(sql).Rows()
	}
	return nil, errors.New("No this database:" + d)
}
